from .BasicSession import BasicSession
from .functions import *

class Session(BasicSession):
	"""
	# Ram id table:
	# 	0 - 2:	template generation temp
	# 	3:		finger to match
	# 	4:		finger to be matched
	# 	5:		temp save merged template
	"""

	def __init__(self, debug = False, imageType = 0):
		super(Session, self).__init__(debug = debug)
		self.imageType = imageType

	def getDeviceInfo(self):
		self.sendCommand(4)
		return self.readResponse()

	def detectFinger(self):
		self.sendCommand(0x21)
		retData = self.readResponseMessage()
		if retData == None: return False
		retData = parseByte(retData)
		if retData == 1: return True
		else: return False

	def saveImage(self):
		self.sendCommand(0x20)
		retData = self.readResponseMessage()
		if retData != None: return True
		else: return False

	# Read fingerprint(image from the module's image buffer)
	# The image is lower-left started
	def getImage(self, imageType = None):
		if imageType == None: imageType = self.imageType
		# Read image informations
		cmdData = makeByte(imageType)
		self.sendCommand(0x22, cmdData)
		imgInfo = self.readResponseMessage()
		if not imgInfo: return None
		imgWidth = parseWord(imgInfo[0:4])
		imgHeight = parseWord(imgInfo[4:8])
		imgDataLength = imgWidth * imgHeight
		# print("Size:", imgWidth, imgHeight, imgDataLength)

		# read image data
		readBytes = 0 # Number of bytes read
		imgData = []
		while readBytes < imgDataLength:
			imgDataStr = self.readResponseData(min(imgDataLength - readBytes, 496) + 2)
			if not imgDataStr: return None
			imgDataSegLen = parseWord(imgDataStr[0:4])
			imgDataStr = imgDataStr[4 : 4 + imgDataSegLen * 2]
			for i in range(0, len(imgDataStr) / 2):
				pointByte = imgDataStr[i * 2 : (i + 1) * 2]
				imgData.append(parseByte(pointByte))
			readBytes += imgDataSegLen
		# print("read complete. bytes read:", len(imgData), readBytes)
		imgMatrix = []
		i = 0
		for r in range(0, imgHeight):
			imgRow = []
			for c in range(0, imgWidth):
				# pointByte = imgDataStr[i * 2 : (i + 1) * 2]
				# imgRow.append(parseByte(pointByte))
				imgRow.append(imgData[i])
				i = i + 1
			imgMatrix.append(imgRow)
		return imgMatrix

	def putImage(self, imageData, imageWidth = None, imageHeight = None) :
		if not imageWidth: imageWidth = len(imageData[0])
		if not imageHeight: imageHeight = len(imageData)
		# Send command
		cmdData = makeWord(imageWidth) + makeWord(imageHeight)
		self.sendCommandMessage(0x23, cmdData)
		retData = self.readResponseMessage()
		if retData == None: return False
		# Encode the image data
		imageDataFlatten = []
		for r in imageData:
			for c in r:
				imageDataFlatten.append(c)
		imgDataLength = len(imageDataFlatten)
		bytesPacked = 0
		packages = []
		while bytesPacked < imgDataLength:
			packLen = min(imgDataLength - bytesPacked, 496)
			packData = imageDataFlatten[bytesPacked : bytesPacked + packLen]
			packDataStr = ""
			for _byte in packData:
				packDataStr += makeByte(_byte)
			packDataStr = makeWord(bytesPacked) + packDataStr
			packages.append(packDataStr)
			bytesPacked += packLen
		# Send command data packages
		for pack in packages:
			self.sendCommandData(0x23, pack)
			retData = self.readResponseData(0)
			if retData == None: return False
		return True

	def getAvailableTemplateId(self, rangeStart = 1, rangeEnd = 1000):
		if rangeStart < 1: return None
		if rangeEnd > 1000: return None
		if rangeStart > rangeEnd: return None
		self.sendCommandMessage(0x45, makeWord(rangeStart) + makeWord(rangeEnd))
		retData = self.readResponseMessage()
		if retData == None: return None
		if len(retData) == 4: return parseWord(retData)
		return None

	def generateTemplate(self, ramId = 0):
		if ramId != 0 and ramId != 1 and ramId != 2: return False
		self.sendCommandMessage(0x60, makeWord(ramId))
		result = self.readResponseMessage()
		if result == None: return False
		return True

	def mergeTemplate(self, ramId = 0, count = 2):
		if count != 2 and count != 3: return False
		self.sendCommandMessage(0x61, makeWord(ramId) + makeByte(count))
		retData = self.readResponseMessage()
		if retData == None: return False
		return True

	def storeChar(self, templateId = None, ramId = 0):
		if templateId == None: templateId = self.getAvailableTemplateId()
		# print('generate templateId: ', templateId)
		if templateId == None: return None
		if templateId < 1 or templateId > 1000: return None
		# print('check ok')
		self.sendCommandMessage(0x40, makeWord(templateId) + makeWord(ramId))
		retData = self.readResponseMessage(allowedReturnCodes = [0x18])
		if retData == None: return None
		if len(retData) == 0: return templateId
		if len(retData) == 4: return parseWord(retData)
		return None

	def loadChar(self, ramId = 0, templateId = 0):
		if templateId < 1 or templateId > 1000: return False
		self.sendCommandMessage(0x41, makeWord(templateId) + makeWord(ramId))
		retData = self.readResponseMessage()
		if retData == None: return False
		return True

	def matchChar(self, ramId1 = 0, ramId2 = 1):
		self.sendCommandMessage(0x62, makeWord(ramId1) + makeWord(ramId2))
		retData = self.readResponseMessage()
		if retData == None: return False
		return True

	def searchChar(self, ramId = 0, tplRangeStart = 1, tplRangeEnd = 1000):
		if tplRangeStart < 1: return None
		if tplRangeEnd > 1000: return None
		if tplRangeStart > tplRangeEnd: return None
		self.sendCommandMessage(0x63, makeWord(ramId) + makeWord(tplRangeStart) + makeWord(tplRangeEnd))
		retData = self.readResponseMessage()
		if retData == None: return None
		if len(retData) == 3 * 2: 
			tplId = retData[0:4]
			tplId = parseWord(tplId)
			return tplId
		return None

	def deleteChar(self, tplRangeStart = 1, tplRangeEnd = 1000):
		if tplRangeStart < 1: return None
		if tplRangeEnd > 1000: return None
		if tplRangeStart > tplRangeEnd: return None
		self.sendCommandMessage(0x44, makeWord(tplRangeStart) + makeWord(tplRangeEnd))
		retData = self.readResponseMessage(allowedReturnCodes = [0x12])
		if retData == None: return False
		else: return True

	def uploadChar(self, ramId = 0):
		self.sendCommandMessage(0x42, makeWord(ramId))
		retData = self.readResponseMessage()
		if retData == None: return None
		dataLen = parseWord(retData)
		retData = self.readResponseData(dataLen)
		if retData == None: return None
		return retData

	def downloadChar(self, ramId = 0, data = ""):
		dataLen = len(data) / 2
		self.sendCommandMessage(0x43, makeWord(2 + dataLen))
		retData = self.readResponseMessage()
		if retData == None: return False
		self.sendCommandData(0x43, makeWord(ramId) + data)
		retData = self.readResponseData(0)
		if retData == None: return False
		return True



